﻿#include <iostream>
#include <map>
#include <list>
#include <set>
#include <vector>
#include <array>
#include <thread>
#include "krpc/netserver.h"
#include "krpc/service.h"
#include "file.h"

void test_notargs_and_notret()
{
	std::cout << "test_notargs_and_notret called" << std::endl;
}

void test_notret(std::string str)
{
	std::cout << "str is " << str << std::endl;
}

std::string test_notargs()
{
	return "test_notargs called!";
}

std::string test_has_args_and_ret(int a, short b, char c, bool d)
{
	std::string str = std::to_string(a);
	str += ' ';
	str += std::to_string((int)b);
	str += ' ';
	str += std::to_string((int)c);
	str += ' ';
	str += (d ? "true" : "false");
	std::cout << str << std::endl;
	return str;
}

struct SelfClass
{
	std::vector<int> vec;
	std::list<std::set<int>> ls;
	std::map<std::string, std::array<int, 3>> ma;

	MSGPACK_DEFINE(vec, ls, ma);
};

SelfClass get_self_class()
{
	SelfClass sc;
	sc.vec = {10, 20, 30};
	sc.ls = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
	sc.ma.emplace("111", std::array<int, 3>{123, 456, 789});
	std::cout << "get_self_class() called" << std::endl;
	return sc;
}

std::string upload_file(std::string path)
{
	common::file file(path.c_str());	
	std::string content;
	auto sz = file.Read(content);
	std::cout << "read file " << path << ", size: " << content.size() << std::endl;
	return content;
}

struct TestClass
{
	void voidtest()
	{
		std::cout << "TestClass::voidtest() called!" << std::endl;
	}
	void print(std::string str)
	{
		std::cout << str << std::endl;
	}
	static int count()
	{
		return 12345;
	}

	int operator()(int a, int b) const
	{
		return a + b;
	}

	int plus(int a, int b)
	{
		return a + b;
	}
};

	struct hehe
	{
		int a;
		int b;
		MSGPACK_DEFINE(a,b);
	};
int main(int argc, char const *argv[])
{
	//KRPC::TS server(9000);
	//KRPC::US server(9000);
	//KRPC::LDS server("unix");
	KRPC::LSS server("unix");
	KRPC::Service service(server);

#if 1
	//test c global function
	service.bind("test_notargs_and_notret", &test_notargs_and_notret);
	service.bind("test_notret", &test_notret);
	service.bind("test_notargs", &test_notargs);
	service.bind("test_has_args_and_ret", &test_has_args_and_ret);

	service.bind("get_self_class", get_self_class);

	service.bind("upload_file", upload_file);

	//test lambda
	service.bind("getString", [](int i)->std::string{
		std::cout << "i = " << i << std::endl;
		return "hello wrold!";
	});

	//test class member function
	TestClass tc;	
	service.bind("voidtest", &TestClass::voidtest, &tc);
	service.bind("print", &TestClass::print, &tc);	
	service.bind("count", &TestClass::count);
	//std::function<int(int, int)> f1 = tc;
	//service.bind("std::function", f1);
	service.bind("operator1()", tc);
	const TestClass &ttc = tc;
	service.bind("operator()", ttc);

	//std::function<int(int)> f2 = std::bind(&TestClass::plus, &tc, std::placeholders::_1, 100);
	//service.bind("plus", f2);
	service.bind("plus", &TestClass::plus, &tc, std::placeholders::_1, 100);
	std::thread th([&service]{
		std::string str("hello wrold");
		int i = 0;
		while (1) {
			std::this_thread::sleep_for(std::chrono::milliseconds(500));
			service.publish("sub", str, i);
			str[0] += 1;
			i++;
		}
	});
	th.detach();
#endif
#if 1	//增加一个发布对象的测试

	std::thread th2([&service]{
		hehe hi;
		hi.a=1;
		hi.b=100;
		while(1) {
			std::this_thread::sleep_for(std::chrono::seconds(3));
			hi.a++;
			hi.b--;
			//service.publish("sub", std::string("hello wrold"), 100);
			service.publish("hehe", hi);
		}
	});
	th2.detach();
#endif

	service.run();
	return 0;
}
